Tools Plus’s event modifier field provides information identical to that obtained directly from the Macintosh’s Event Manager. To reiterate, the Modifiers field of the event record contains information about the position of the Caps Lock, Shift, Option, Command and Control keys at the time of the event, as well as the position of the mouse button. This can be used, for example, to detect if the Command key was down when a key was typed (i.e. a Command-key sequence). In effect, your application could respond to command key sequences that are not menu equivalents by using this method. Your application could also place special significance on Option-Clicks. The most common use, however, is Shift-Tab that indicates that the user wants to tab to the previous field.
In the Macintosh’s Event Manager, the Modifiers field of the event record is an integer. Several of the bits indicate the state of the various modifiers, as detailed in Inside Macintosh Vol 1 and Vol 5. Tools Plus goes a step further to and automatically decodes individual modifiers in the field. This is handled through a union in C, and a variant record in Pascal.
Event Modifiers Using C
```````````````````````
When programming in C, Tools Plus’s Modifiers structure is a union that lets you access both the integer obtained from the Macintosh’s Event Manager, as well as the individual flags (bits) within the integer. Tools Plus’s Modifiers structure looks like this:
union TPModifiersRec { /*This variable record contains */
/* an event's "modifiers" in 2 */
/* formats… */
/* • Macintosh Event: */
int Num; /* integer (bit operations */
/* required) */
/* • Modifier integer parsed */
struct { /* into components: */
unsigned int bit15 :1; /* (reserved bit) */
unsigned int bit14 :1; /* (reserved bit) */
unsigned int bit13 :1; /* (reserved bit) */
unsigned int ControlKey :1; /* Control key was down at event */
unsigned int OptionKey :1; /* Option key was down at event */
unsigned int CapsLock :1; /* Caps Lock was down at event */
unsigned int ShiftKey :1; /* Shift key was down at event */
unsigned int CmdKey :1; /* Command key was down at event */
unsigned int MouseUp :1; /* Mouse button was UP at event */
unsigned int bit6 :1; /* (reserved bit) */
unsigned int bit5 :1; /* (reserved bit) */
unsigned int bit4 :1; /* (reserved bit) */
unsigned int bit3 :1; /* (reserved bit) */
unsigned int bit2 :1; /* (reserved bit) */
unsigned int bit1 :1; /* (reserved bit) */
unsigned int bit0 :1; /* (reserved bit) */
} Bits; /* */
};
typedef union TPModifiersRec TPModifiersRec;
Whenever you access any of the individual modifier flags, you reference the “bits” part of the structure. For example, if you want to check if the Command key was down and the Option key was up when a key was typed, you can use an expression such as this:
if ((Poll.Modifiers.Bits.CmdKey) && (!Poll.Modifiers.Bits.OptionKey))
In contrast, the Modifiers field provided by the Macintosh’s Event Manager requires bitwise “And” operations to determine if a bit is set or not, thereby resulting in source code that looks more cryptic. The following line duplicates the previous example’s functionality using bitwise “And” operations instead of the available bits:
if ((Poll.Modifiers.Num & cmdKey) && !(Poll.Modifiers.Num & optionKey))
When you are working with the Modifiers structure, you may perform operations exclusively on the integer variant of the structure, on the bits variant, or if you choose, you can mix and match as needed. Several constants representing the “bit-equivalents” for the various flags contained in the Modifiers integer are available as follows:
/*Modifier masks */
#define btnState 0x0080 /*set to 1 if mouse button is up */
#define cmdKey 0x0100 /*set to 1 if Command key is down */
#define shiftKey 0x0200 /*set to 1 if Shift key is down */
#define alphaLock 0x0400 /*set to 1 if the Caps Lock key is down */
#define optionKey 0x0800 /*set to 1 if the option key is down */
#define controlKey 0x1000 /*set to 1 if the control key is down */
Event Modifiers Using Pascal
````````````````````````````
When programming in Pascal, Tools Plus’s Modifiers structure is a variant record that lets you access both the integer obtained from the Macintosh’s Event Manager, as well as the individual flags (bits) within the integer. Tools Plus’s Modifiers record looks like this:
{= Polling record's "event modifiers" info}
TPModifiersRec = packed record {This variable record contains }
{ an event's "modifiers" in 2 }
case integer of { formats… }
0: ( { • Macintosh Event: }
Num: integer { integer (bit operations }
); { required) }
1: ( { • Modifier integer parsed }
{ into components: }
bit15, bit14, bit13: boolean; { (reserved bits) }
ControlKey: boolean; { Control key was down at event }
OptionKey: boolean; { Option key was down at event }
CapsLock: boolean; { Caps Lock was down at event }
ShiftKey: boolean; { Shift key was down at event }
CmdKey: boolean; { Command key was down at event }
MouseUp: boolean; { Mouse button was UP at event }
bit6, bit5, bit4, bit3, bit2, { (reserved bits) }
bit1,bit0: boolean; { }
); { }
end;
You use each field in the record as an individual modifier variable. For example, if you want to check if the Command key was down and the Option key was up when a key was typed, you can use an expression such as this:
if Poll.Modifiers.CmdKey and not Poll.Modifiers.OptionKey then
In contrast, the Modifiers field provided by the Macintosh’s Event Manager requires bitwise “And” operations to determine if a bit is set or not, thereby resulting in source code that looks more cryptic. The following line duplicates the previous example’s functionality using bitwise “And” operations instead of the available bits:
if (BitAnd(Poll.Modifiers.Num,cmdKey) <> 0) and
BitAnd(Poll.Modifiers.Num,optionKey) = 0) then
When you are working with the Modifiers record, you may perform operations exclusively on the integer variant of the record, on the bits variant, or if you choose, or you can mix and match as needed. Several constants representing the “bit-equivalents” for the various flags contained in the Modifiers integer are available as follows:
CONST {Modifier masks }
btnState =$0080; {set to 1 if mouse button is up }
cmdKey =$0100; {set to 1 if Command key is down }
shiftKey =$0200; {set to 1 if Shift key is down }
alphaLock =$0400; {set to 1 if the Caps Lock key is down }
optionKey =$0800; {set to 1 if the option key is down }
controlKey=$1000; {set to 1 if the control key is down }
function PollSystem(var Poll:TPPollRecord): BOOLEAN;
The Poll record contains all the information about an event.
The function’s value will be true if an event was obtained, and false if an event was not obtained. PollSystem should be called as often as possible (at least sixty times per second) to keep desk accessories, automatic processes, and other applications running under MultiFinder or System 7 running smoothly.
PollSystem calls the Toolbox’s GetNextEvent function which performs all necessary task switching and background processing control. Desk Accessories’ get their events, and other applications that are also running under MultiFinder or System 7 (or later) get their required processing. It is important that your application does not do a lot of processing between calls to PollSystem, or it will be a “CPU hog” and make other applications run sluggishly or in spurts and jumps.
Warning: Do not call PollSystem from within a BeginUpdateScreen /
EndUpdateScreen structure.
Tools Plus Event Codes
``````````````````````
Each event reported by PollSystem is identified by the first field of the polling record, Poll.What. The Poll.What field contains the event code which tells your application what to do with the event record’s information. Constants are used to identify event codes as follows:
CONST {Tools Plus event codes }
doNothing =0; {no event }
doChgWindow =1; {user clicked in an inactive window }
doRefresh =2; {a window has to be refreshed }
doGoAway =3; {the Go-Away box was clicked }
doButton =4; {button was clicked }
doMenu =5; {menu was selected }
doKeyDown =6; {a keyboard key was pressed }
doAutoKey =7; {a keyboard key is auto-repeating }
doKeyUp =8; {a keyboard key was released }
doClickField =9; {mouse clicked in inactive editing field}
doScrollBar =10; {mouse clicked in a scroll bar }
doListBox =11; {some sort of List Box activity }
doClick =12; {mouse click/drag [1..3] }
doClickControl=101; {mouse clicked in a custom control }
doManualEvent =102; {manually processed events }
doMoveWindow =103; {a window was moved by user }
doGrowWindow =104; {a window was “grown” by user }
doClickDesk =105; {mouse clicked in the desk top }
doZoomWindow =106; {zoom box was clicked by user }
doSuspend =107; {appl. suspended (in background) }
doResume =108; {appl. resumed (now active appl.) }
Event codes over 100 will likely be ignored by most applications. All events are detailed later, telling you how to respond to the event and which fields in the event record contain valid information that is related to the event.
What Does PollSystem Do?
````````````````````````
On the surface, it appears that PollSystem is just a fancy way to get an event from the Toolbox Event Manager. Quite to the contrary, PollSystem does a lot of work for you.
The biggest service that PollSystem performs is to keep Tools Plus’s automatic processes running smoothly. To do this, you must understand the difference between an internally processed event, and an externally processed event.
Internally Processed Events
```````````````````````````
An internal event is something that can be processed by Tools Plus without the knowledge or assistance of your application. Hence the term internal means internal to Tools Plus. The internal processing of events is how PollSystem drives its automatic tasks.
An example of an internally processed event can be a key-down event from the Toolbox Event Manager. If the active window belongs to your application and it has an active editing field, the user’s key-strokes will affect the text in the editing field automatically. Since this event was processed internally, no event is reported to your application.
One of the tricks that PollSystem utilizes, is to process as many internal events as it possibly can before returning to your application. It will return to your application when the event queue is empty, or when it encounters an event that cannot be processed internally. Why doesn’t it process just one event at a time? If your application is busy and the user types 10 characters on the keyboard before PollSystem is called, the single call to PollSystem will process all 10 keystrokes! This ensures that Tools Plus’s automatic processes occur as smoothly as possible without accumulating a backlog of events.
Externally Processed Events
```````````````````````````
Whenever PollSystem encounters an event it cannot process internally, it reports the event to your application. An example of this is when the user clicks the close box in the active window. Your application may want to ask the user if he wants to save the changes before closing the document. Therefore, PollSystem only reports a request to close a window, and does not actually close it.
Some events may be ignored by your application. One of these events tells your application that the user dragged a window. Your application may be interested in a window’s co-ordinates at any given time, in which case this event would be crucial. In most cases, applications wouldn’t care if the window is dragged, and would always ignore the event.
Inside PollSystem
`````````````````
Inside PollSystem describes the inner workings of the PollSystem routine. Those programmers who are curious about this aspect, or those that want to know how Toolbox Events are translated into Tools Plus events may find this passage interesting.
Every time your application calls PollSystem, several processes are executed as follows:
(1) Tools Plus’s SystemTasks is called to keep desk accessories running and to keep the insertion point flashing in the active editing field, if one is active.
(2) Desk accessories get any events they may require, and task switching occurs to allow other applications running under MultiFinder or System 7 (or later) get some processing time.
(3) The event queue is checked for an event. If any events exist, the first one is removed from the queue. If the event can be processed internally, it is and this step is repeated.
(4) If an event is obtained that can not be processed internally, the Tools Plus event record is set up to contain all the required information for the event in a format that is readily usable by your application.
(5) The cursor’s position is checked and its shape is changed if required.
(6) PollSystem returns to your application with an event, or a “no event” (false) status.
Translating Toolbox events to Tools Plus events
```````````````````````````````````````````````
Step 3 looks pretty simple when it is summarized in a couple lines, however, the recognition and processing of internal events is quite an extensive duty for Tools Plus. The table below describes this formidable task by listing the Macintosh’s Toolbox Event Manager’s event, the internal processes that follow, and the event that finally reaches your application. Remember that some Toolbox events are processed internally and never reach your application, and some events that reach your program can be ignored.
When PollSystem returns with a value of false it indicates that no event has occurred. This is commonly called a “null event.” Usually, your application won’t do anything other than idle in the main event loop. Applications that do on-going processing should do their work only when they receive a null event.
PollSystem returns with a value of true when an event has occurred. The first field in the polling record is “what,” which tells your application what type of event has occurred. The following section of this chapter describes how your application should respond to each event. It also details any programming considerations that should be taken into account when responding to such an event.
Note: Your application should call PollSystem as often as possible to
allow other applications processing time. If your application
can’t call PollSystem at least 60 times per second, make up the
difference with calls to SystemTasks. Otherwise, periodic
processes, such as a flashing insertion point or a displayed clock